package com.example.demo.thread;

/**
 * @Author: liull
 * @Description:制作两个线程对象，要求使同步块的方式使第一个线程运行两次，然后将自己阻塞起来， 唤醒第二个线程，第二个线程在运行两次，然后将自己阻塞起来，唤醒第一个线程……循环往复
 * @Date: Created in 15:14 2020/4/4
 * @Modified By:
 */
public class WaitAndNotify {

    private static Object lock = new Object();

    private volatile static int state = 1;

    static class ThreadA implements Runnable {
        @Override
        public void run() {
            synchronized (lock) {
                while (true) {
                    if (state != 1) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    // 当state=1时, 轮到线程1打印5次数字
                    for (int j = 0; j < 2; j++) {
                        System.out.println(Thread.currentThread().getName() + "第" + (j + 1) + "次");
                    }
                    // 线程1打印完成后, 将state赋值为2, 表示接下来将轮到线程2打印
                    state = 2;
                    // notifyAll()方法唤醒在t上wait的线程2, 同时线程1将退出同步代码块, 释放t锁
                    lock.notifyAll();
                }
            }
        }
    }

    static class ThreadB implements Runnable {
        @Override
        public void run() {
            synchronized (lock) {
                while (true) {
                    if (state != 2) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    // 当state=1时, 轮到线程1打印5次数字
                    for (int j = 0; j < 2; j++) {
                        System.out.println(Thread.currentThread().getName() + "第" + (j + 1) + "次");
                    }
                    // 线程1打印完成后, 将state赋值为2, 表示接下来将轮到线程2打印
                    state = 1;
                    // notifyAll()方法唤醒在t上wait的线程2, 同时线程1将退出同步代码块, 释放t锁
                    lock.notifyAll();
                }
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new Thread(new ThreadA()).start();
        new Thread(new ThreadB()).start();
    }
}
